home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / madtrb8.arc / XREFT.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1985-02-23  |  20.9 KB  |  609 lines

  1. {$C-,I-,V-,R-,K-}
  2. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  3. {+                                                      +}
  4. {+  PROGRAM TITLE:      Cross Reference Generator       +}
  5. {+                                                      +}
  6. {+  WRITTEN BY:         Peter Grogono                   +}
  7. {+  DATE WRITTEN:       ?                               +}
  8. {+                                                      +}
  9. {+  SUMMARY:                                            +}
  10. {+      1. Output Files:                                +}
  11. {+         a. first output file is a numbered listing   +}
  12. {+            of the input source                       +}
  13. {+         b. second output file is cross reference     +}
  14. {+            with each identifier followed by the      +}
  15. {+            line numbers on which it appears.         +}
  16. {+      2. Listing Device:                              +}
  17. {+         The numbered source listing may optionally   +}
  18. {+         be routed to the screen or printer (but not  +}
  19. {+         both).                                       +}
  20. {+                                                      +}
  21. {+  MODIFICATION RECORD:                                +}
  22. {+      17-APR-84       -Modified for Turbo Pascal so   +}
  23. {+                       $ includes are supported       +}
  24. {+                                                      +}
  25. {+                                                      +}
  26. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  27. PROGRAM XREFG2;
  28. { Cross Reference Generator }
  29. CONST
  30.         alfa_length     =  15;
  31.         dflt_str_len    = 255;
  32.         entrygap        =    0;   { # of blank lines between line numbers}
  33.         heading         : string[23] = 'Cross-Reference Listing';
  34.         headingsize     =    3;   {number of lines for heading}
  35.         LLmax           = dflt_str_len;
  36.         MaxOnLine       =   8;
  37.         Maxlines        = MAXINT; {longest document permitted}
  38.         MaxWordlen      = alfa_length;{longest word read without truncation}
  39.         Maxlinelen      =   80;   {length of output line}
  40.         MaxOnPage       =   60;   {size of output page}
  41.         NumKeys         =   70;   {number of Pascal reseve words}
  42.                                   {Read your Pascal manuals on this one!}
  43.         NumberWidth     =    6;
  44.         space           : char = ' ';
  45. TYPE
  46.         ALFA    = string[alfa_length];
  47.         CHARNAME = (lletter, uletter, digit, blank, quote, atab,
  48.                       EndOfLine, FileMark, otherchar );
  49.         CHARINFO = RECORD
  50.                      name : charname;
  51.                      valu : CHAR
  52.                    END;
  53.         COUNTER = 1..Maxlines;
  54.         pageindex = BYTE;
  55.         Wordindex = 1..MaxWordlen;
  56.         Queuepointer = ^Queueitem;
  57.         Queueitem = RECORD
  58.                         linenumber : counter;
  59.                         NextInQueue: Queuepointer
  60.                     END;
  61.         EntryType = RECORD
  62.                         Wordvalue : alfa;
  63.                         FirstInQueue,
  64.                         lastinQueue: Queuepointer
  65.                      END;
  66.         treepointer = ^node;
  67.         node = RECORD
  68.                  entry : EntryType;
  69.                  left,
  70.                  right : treepointer
  71.                END;
  72.         GenStr  = string[255];
  73. VAR
  74.   bell          : CHAR;
  75.   fatal_error   : BOOLEAN;
  76.   FILE_ID,                      { Input file name }
  77.   PRN_ID,                       { basic file name + '.PRN' }
  78.   New_ID        : string[20];   { basic file name + '.XRF' }
  79.   form_feed     : CHAR;
  80.   Key           : ARRAY[1..NumKeys] OF alfa;
  81.   LISTING       : BOOLEAN;
  82.   tab           : CHAR;
  83.   WordTree      : treepointer;
  84.   GAP           : char      ;
  85.   Currentline: INTEGER;
  86.   FOUT: TEXT; { print output file }
  87.   XOUT: TEXT; { xref  output file }
  88.  
  89.  
  90. PROCEDURE PAGE(VAR fx: TEXT);
  91. BEGIN
  92.   WRITELN(fx);
  93.   WRITE(fx, form_feed);
  94. END;
  95.  
  96. { FUNCTYPE:                                                        }
  97. { Do binary search for keyword in 'key' list.  If found, return    }
  98. { TRUE, else FALSE.                                                }
  99. Function Find_in_Reserve(var kword: alfa) : boolean;
  100. Label Return;
  101. Var
  102.     low, high, mid : integer;
  103. Begin
  104.     low  := 1;
  105.     high := NUMKEYS;
  106.     while (low <= high) do begin
  107.         mid := (low+high) div 2;
  108.         if kword < key[mid] then
  109.             high := mid - 1
  110.         else if kword > key[mid] then
  111.             low  := mid + 1
  112.         else begin
  113.             Find_in_Reserve := TRUE;
  114.             goto Return;
  115.             end;
  116.         end;
  117.     Find_in_Reserve := FALSE;
  118. Return:
  119. End;
  120.  
  121. PROCEDURE BuildTree(VAR tree: treepointer; VAR INFILE: GenStr);
  122. VAR
  123.   CurrentWord : alfa;
  124.   FIN : TEXT; { local input file }
  125.   currchar,                     { Current operative character }
  126.   nextchar      : charinfo;     { Look-ahead character }
  127.   flushing      : (KNOT, DBL, STD, LIT, SCANFN, SCANFN2);
  128.   fname         : string[30];
  129.   DoInclude     : boolean; { TRUE if we discovered include file }
  130.   fbuffer       : string[255];  { Format buffer - before final Print }
  131.   LineIn        : string[255];
  132.   LineInLast    : string[255];
  133.   cp            : 0..255;
  134.   xeof,                 { EOF status AFTER a read }
  135.   xeoln         : BOOLEAN;      { EOLN status after a read }
  136.  
  137.    PROCEDURE Entertree(VAR subtree: treepointer;
  138.                            Word   : alfa;
  139.                            line   :counter);
  140.    VAR
  141.      nextitem : Queuepointer;
  142.    BEGIN
  143.      IF subtree=nil THEN
  144.        BEGIN {create a new entry}
  145.          NEW(subtree);
  146.          WITH subtree^ DO BEGIN
  147.            left := nil;
  148.            right := nil;
  149.            WITH entry DO BEGIN
  150.              Wordvalue := Word;
  151.              NEW(FirstInQueue);
  152.              LastinQueue := FirstInQueue;
  153.              WITH FirstInQueue^ DO BEGIN
  154.                 linenumber := line;
  155.                 NextInQueue := nil;
  156.              END;{WITH FirstInQueue}
  157.            END;{WITH entry}
  158.          END;{WITH subtree}
  159.        END {create a new entry}
  160.      ELSE {append a list item}
  161.        WITH subtree^, entry DO
  162.          IF Word=Wordvalue THEN
  163.            BEGIN
  164.              IF lastinQueue^.linenumber <> line THEN
  165.                 BEGIN
  166.                   NEW(nextitem);
  167.                   WITH Nextitem^ DO BEGIN
  168.                     linenumber := line;
  169.                     NextInQueue := nil;
  170.                   END;{WITH}
  171.                   lastinQueue^.NextInQueue := Nextitem;
  172.                   lastinQueue := nextitem;
  173.                 END;
  174.            END
  175.          ELSE
  176.            IF Word < Wordvalue THEN
  177.              Entertree(left,Word,line)
  178.            ELSE
  179.              Entertree(right,Word,line);
  180.    END;{Entertree}
  181.  
  182. Procedure ReadC({updating} VAR nextchar : charinfo;
  183.                 {returning}VAR currchar : charinfo );
  184. Var
  185.   Look          : char; { Character read in from File }
  186. BEGIN   {+++ File status module. +++
  187.    Stores file status "AFTER" a read.
  188.    NOTE this play on words - after one char is
  189.    actually "PRIOR TO" the next character               }
  190.   if xeoln then begin
  191.      LineInLast := LineIn;
  192.      if (not EOF(FIN)) then begin
  193.         readln(FIN, LineIn);
  194.         cp := 0;
  195.         xeoln := FALSE;
  196.         end
  197.       else
  198.         xeof := TRUE;
  199.       end;
  200.   if cp >= length(LineIn) then begin
  201.      xeoln := TRUE;
  202.      xeof  := EOF(FIN);
  203.      Look  := ' ';
  204.      end
  205.   else begin
  206.      cp := cp + 1;
  207.      Look := LineIn[cp];
  208.      End;
  209.         {+++ current operative character module +++}
  210.   currchar := nextchar;
  211.         {+++ Classify the character just read +++}
  212.   WITH nextchar DO BEGIN{ Look-ahead character name module }
  213.     IF xeof THEN
  214.         name := FileMark
  215.     ELSE IF xeoln THEN
  216.         name := EndOfLine
  217.     ELSE IF Look IN ['a'..'z'] THEN {lower case plus}
  218.         name := lletter
  219.     ELSE IF Look IN ['^','$','_','A'..'Z'] THEN {upper case}
  220.         name := uletter
  221.     ELSE IF Look IN ['0'..'9'] THEN {digit}
  222.         name := digit
  223.     ELSE IF Look = '''' THEN
  224.         name := quote
  225.     ELSE IF Look = TAB THEN
  226.         name := atab
  227.     ELSE IF Look = space THEN
  228.         name := blank
  229.     ELSE
  230.         name := otherchar;
  231.     CASE name of{ store character value module }
  232.         EndOfLine,
  233.         FileMark:       Valu := space;
  234.         lletter:        Valu := upcase(look);       { Cnvrt to uppcase }
  235.         ELSE            valu := look;
  236.     END{ case name of };
  237.   End{ Look-ahead character name module };
  238. END; {of ReadC}
  239.  
  240. PROCEDURE GetL( VAR fbuffer :  GenStr      );
  241. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  242. {+      Get a line of text into users buffer.           +}
  243. {+      Flushes comment lines:                          +}
  244. {+      Flushes lines of Literals:  'this is it'        +}
  245. {+      Ignores special characters & tabs:              +}
  246. {+      Recognizes End of File and End of Line.         +}
  247. {+                                                      +}
  248. {+GLOBAL                                                +}
  249. {+      flushing : (KNOT, DBL, STD, LIT, SCANFN);       +}
  250. {+      LLmax   = 0..Max Line length;                   +}
  251. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  252. VAR
  253.   state : (scanning, terminal, overflow);
  254.   sawdot : boolean;
  255. BEGIN { GetL }
  256.    fbuffer := '';
  257.    fname := '';
  258.    fatal_error := FALSE;
  259.    state := scanning;
  260.   REPEAT
  261.     ReadC(nextchar, currchar);
  262.     IF (length(fbuffer) >= LLmax) THEN{ exceeded length of buffer }
  263.       BEGIN{ reset EOLN }
  264.         fatal_error := TRUE;
  265.         state := overflow;
  266.         fbuffer := '';
  267.         WRITE(bell);
  268.         WRITELN('EXCEEDED LENGTH OF INPUT BUFFER');
  269.       END
  270.     ELSE
  271.       BEGIN
  272.         IF (currchar.name IN [FileMark,EndOfLine]) THEN
  273.           state:=terminal{ END of line or END of file };
  274.         CASE flushing of
  275.             KNOT:
  276.                 CASE currchar.name of
  277.                 lletter, uletter, digit, blank:
  278.                         BEGIN{ store }
  279.                         fbuffer := concat(FBUFFER,CURRCHAR.VALU) ;
  280.                         END;
  281.                 atab, quote, otherchar:
  282.                         BEGIN{   Flush comments -convert
  283.                                  tabs & other chars to spaces }
  284.                         IF (currchar.valu='(') and (nextchar.valu='*')
  285.                           THEN flushing := DBL
  286.                         ELSE IF (currchar.valu='{') THEN
  287.                            flushing := STD
  288.                         ELSE IF currchar.name=quote THEN
  289.                            flushing := LIT;
  290.                         { convert to a space }
  291.                            fbuffer := concat(fbuffer,GAP);
  292.                         END;
  293.                 ELSE         { END of line -or- file mark }
  294.                         fbuffer := concat(fbuffer,currchar.valu)
  295.                 END{ case currchar name of };
  296.             DBL:  { scanning for a closing  - double comment }
  297.                 IF (currchar.valu ='*') and (nextchar.valu =')')
  298.                   THEN flushing := KNOT;
  299.             STD:  begin { scanning for a closing curley  }
  300.                   IF currchar.valu = '}' THEN
  301.                       flushing := KNOT;
  302. { Check if incl } if (currchar.valu = '$') and (nextchar.valu = 'I') then
  303.                       flushing := SCANFN;
  304.                   end;
  305.             LIT:  { scanning for a closing quote }
  306.                   IF currchar.name = quote THEN
  307.                     flushing := KNOT;
  308.             SCANFN: if (nextchar.valu<>' ') and (nextchar.valu<>TAB) then
  309.                     begin
  310.                     flushing := SCANFN2;
  311.                     SAWDOT := FALSE;
  312.                     end;
  313.             SCANFN2: if (currchar.valu in ['A'..'Z','0'..'9','.'])
  314.                      then begin
  315.                         fname := concat(fname, currchar.valu);
  316.                         if currchar.valu = '.' then SAWDOT := TRUE;
  317.                         end
  318.                      else begin
  319.                         if length(fname) = 0 then  { Make sure we ignore $I-}
  320.                            DoInclude := FALSE      { compiler directive }
  321.                         else begin
  322.                            if not SAWDOT then fname := Concat(fname, '.PAS');
  323.                            DoInclude := TRUE;
  324.                            end;
  325.                         flushing := STD;
  326.                         end;
  327.         END{ flushing case }
  328.       END{ ELSE }
  329.   UNTIL (state<>scanning);
  330. END; {of GetL}
  331.  
  332. PROCEDURE ReadWord;
  333. {++++++++++++++++++++++++++++++++++++++++++++++++}
  334. {+                                              +}
  335. {+       Analyze the Line into "words"          +}
  336. {+                                              +}
  337. {++++++++++++++++++++++++++++++++++++++++++++++++}
  338. LABEL   1;
  339. VAR
  340.   ix,           {temp indexer}
  341.   idlen,        {length of the word}
  342.   Cpos : BYTE; { Current Position pointer }
  343. BEGIN{ ReadWord }
  344.   Cpos := 1; { start at the beginning of a line }
  345.   WHILE Cpos < length(fbuffer) DO
  346.     BEGIN {Cpos<length(fbuffer)}
  347.       WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos]=space) DO
  348.         Cpos:=Cpos + 1;    {--- skip spaces ---}
  349.       idlen := 0;
  350.       WHILE (Cpos < length(fbuffer)) AND (fbuffer[Cpos ] <> space) DO
  351.         BEGIN{ accept only non-spaces }
  352.           IF idlen < MaxWordlen THEN
  353.             BEGIN
  354.               idlen := idlen + 1;
  355.               CurrentWord[idlen] := fbuffer[Cpos];
  356.             END;
  357.           Cpos := Cpos +1;
  358.         END{ WHILE };
  359.       CurrentWord[0] := chr(idlen);
  360.       IF length(CurrentWord)=0 THEN {no word was found} GOTO 1;
  361.  
  362.       IF (not Find_in_Reserve(CurrentWord)) and    {check if reserved word}
  363.          (not (CurrentWord[1] in ['0'..'9'])) then {or numeric constant}
  364.          EnterTree(tree,CurrentWord,Currentline);
  365.  
  366.       1:{Here is no word <length of word=0>};
  367.     END; {WHILE Cpos<length(fbuffer)}
  368. END; {of Readword}
  369.  
  370. BEGIN{BuildTree}
  371.    flushing := KNOT{ flushing };
  372.    DoInclude := FALSE;
  373.    xeoln := TRUE;
  374.    xeof  := FALSE;
  375.    LineIn := '';
  376.    ASSIGN(FIN,INFILE);
  377.    RESET(FIN);
  378.    IF IOresult <> 0 THEN
  379.       BEGIN
  380.         WRITE(BELL);
  381.         WRITELN('File ',INFILE,' not found !!!!!!');
  382.         fatal_error := TRUE;
  383.       END;
  384.      nextchar.name := blank;       { Initialize next char to a space }
  385.      nextchar.valu := space;
  386.      ReadC({update}    nextchar,   { Initialize current char to space }
  387.            {returning} currchar);  { First char from file in nextchar }
  388.      WHILE ((currchar.name<>filemark) AND (NOT fatal_error)) DO
  389.        BEGIN
  390.          Currentline := Currentline + 1;
  391.          GetL(fbuffer) { attempt to read the first line };
  392.          Writeln(Fout, Currentline:6,': ',LineInLast);
  393.          IF listing THEN Writeln(Currentline:6,': ',LineInLast)
  394.          else if (Currentline mod 100) = 0 then
  395.            writeln('ON LINE : ',Currentline:0);
  396.          ReadWord; {Analyze the Text into single 'words' }
  397.          if DoInclude then Begin
  398.             BuildTree(tree, fname);  { recursively do include }
  399.             DoInclude := FALSE;
  400.             end;
  401.        END; {While}
  402.        close(FIN);
  403.  
  404. END; {of BuildTree}{CLOSE(PRN_ID);}
  405.  
  406. PROCEDURE PrintTree(tree: treepointer);
  407. {
  408. GLOBAL
  409.         MaxOnLine   = max line references per line
  410.         NumberWidth = field for each number
  411. }
  412. VAR
  413.   pageposition: pageindex;
  414.    PROCEDURE PrintEntry(subtree: treepointer;
  415.                         VAR position: pageindex);
  416.    VAR  ix: Wordindex;
  417.         itemcount : 0..Maxlinelen;
  418.         itemptr : Queuepointer;
  419.         PROCEDURE PrintLine(VAR Currentposition: pageindex;
  420.                                 newlines: pageindex);
  421.         VAR
  422.           linecounter: pageindex;
  423.         BEGIN
  424.           IF (Currentposition + newlines) < MaxOnPage THEN
  425.             BEGIN
  426.                 FOR linecounter:=1 TO newlines DO WRITELN(XOUT);
  427.                 Currentposition := Currentposition + newlines;
  428.             END
  429.           ELSE
  430.             BEGIN
  431.               PAGE(XOUT);
  432.               WRITELN(XOUT,heading);
  433.               FOR linecounter := 1 TO headingsize - 1 DO
  434.                  WRITELN(XOUT);
  435.               Currentposition := headingsize + 1;
  436.             END
  437.         END;{PrintLine}
  438.  
  439.    BEGIN{PrintEntry}
  440.      IF subtree<>nil THEN
  441.         WITH subtree^ DO BEGIN
  442.           PrintEntry(left,position);
  443.           PrintLine(position,entrygap + 1);
  444.           WITH entry DO BEGIN
  445.             FOR ix := 1 to length(WordValue) do WRITE(XOUT, WordValue[ix]);
  446.             WRITE(XOUT, space:(MaxWordLen-length(WordValue)));
  447.             itemcount := 0;
  448.             itemptr := FirstInQueue;
  449.             WHILE itemptr <> nil DO
  450.               BEGIN
  451.                 itemcount := itemcount + 1;
  452.                 IF itemcount > MaxOnLine THEN
  453.                   BEGIN
  454.                     PrintLine(position,1);
  455.                     WRITE(XOUT, space:MaxWordlen);
  456.                     itemcount := 1;
  457.                   END;
  458.                 WRITE(XOUT, itemptr^.linenumber: numberwidth);
  459.                 itemptr := itemptr^.NextInQueue;
  460.               END;{WHILE}
  461.           END; {WITH entry}
  462.           PrintEntry(right,position);
  463.         END; {WITH subtree^}
  464.    END; {PrintEntry}
  465.  
  466. BEGIN{PrintTree}
  467.   PagePosition := MaxOnPage;
  468.   PrintEntry(tree,PagePosition);
  469. END; {of PrintTree}{CLOSE(New_ID);}
  470.  
  471. FUNCTION ConnectFiles: boolean;
  472. TYPE
  473.   Linebuffer = string[80];
  474. VAR
  475.   ix  : BYTE;
  476. BEGIN{ ConnectFiles }
  477.   fatal_error := FALSE;
  478.   ConnectFiles := TRUE;
  479.    WRITELN('Enter Complete Filenames') ;
  480.    WRITELN ;
  481.    WRITE('Input File: ');
  482.    READLN(FILE_ID);
  483.    WRITELN;
  484.    WRITE('Printed output: ');
  485.    READLN(PRN_ID);
  486.    WRITELN;
  487.    WRITE('Cross-Reference output: ');
  488.    READLN(NEW_ID);
  489.    WRITELN;
  490.    Assign(fout,PRN_ID);
  491.    Rewrite(FOUT);
  492.    if IOresult <> 0 then begin
  493.       writeln('Could not open ',PRN_ID,' (print output file).');
  494.       ConnectFiles := FALSE;
  495.       fatal_error  := TRUE;
  496.       end;
  497.   assign(xout,NEW_ID);
  498.   Rewrite(Xout) ;
  499.   if IOresult <> 0 then begin
  500.      writeln('Could not open ',NEW_ID,' (xref output file).');
  501.      ConnectFiles := FALSE;
  502.      fatal_error := TRUE;
  503.      end;
  504. END{ of ConnectFiles };
  505.  
  506. PROCEDURE Initialize;
  507. VAR
  508.   Ch: CHAR;
  509. BEGIN
  510.   bell := ^G; GAP := ' ' ;
  511.   Currentline := 0;
  512.   IF ConnectFiles THEN
  513.     BEGIN
  514.         Key[ 1] := 'ABSOLUTE';
  515.         Key[ 2] := 'AND';
  516.         Key[ 3] := 'ARRAY';
  517.         Key[ 4] := 'ASSIGN';
  518.         Key[ 5] := 'BEGIN';
  519.         Key[ 6] := 'BOOLEAN';
  520.         Key[ 7] := 'BYTE';
  521.         Key[ 8] := 'CASE';
  522.         Key[ 9] := 'CHAIN';
  523.         Key[10] := 'CHAR';
  524.         Key[11] := 'CHR';
  525.         Key[12] := 'CLOSE';
  526.         Key[13] := 'CONCAT';
  527.         Key[14] := 'CONST';
  528.         Key[15] := 'COPY';
  529.         Key[16] := 'DELETE';
  530.         Key[17] := 'DIV';
  531.         Key[18] := 'DO';
  532.         Key[19] := 'DOWNTO';
  533.         Key[20] := 'ELSE';
  534.         Key[21] := 'END';
  535.         Key[22] := 'EOF';
  536.         Key[23] := 'EOLN';
  537.         Key[24] := 'EXECUTE';
  538.         Key[25] := 'EXIT';
  539.         Key[26] := 'EXTERNAL';
  540.         Key[27] := 'FALSE';
  541.         Key[28] := 'FILE';
  542.         Key[29] := 'FILLCHAR';
  543.         Key[30] := 'FOR';
  544.         Key[31] := 'FORWARD';
  545.         Key[32] := 'FUNCTION';
  546.         Key[33] := 'GOTO';
  547.         Key[34] := 'IF';
  548.         Key[35] := 'IN';
  549.         Key[36] := 'INLINE';
  550.         Key[37] := 'INPUT';
  551.         Key[38] := 'INTEGER';
  552.         Key[39] := 'LABEL';
  553.         Key[40] := 'LENGTH';
  554.         Key[41] := 'MOD';
  555.         Key[42] := 'NIL';
  556.         Key[43] := 'NOT';
  557.         Key[44] := 'OF';
  558.         Key[45] := 'OR';
  559.         Key[46] := 'ORD';
  560.         Key[47] := 'OUTPUT';
  561.         Key[48] := 'PACKED';
  562.         Key[49] := 'PROCEDURE';
  563.         Key[50] := 'PROGRAM';
  564.         Key[51] := 'REAL';
  565.         Key[52] := 'RECORD';
  566.         Key[53] := 'REPEAT';
  567.         Key[54] := 'SET';
  568.         Key[55] := 'SHL';
  569.         Key[56] := 'SHR';
  570.         Key[57] := 'STRING';
  571.         Key[58] := 'SUCC';
  572.         Key[59] := 'TEXT';
  573.         Key[60] := 'THEN';
  574.         Key[61] := 'TO';
  575.         Key[62] := 'TRUE';
  576.         Key[63] := 'TYPE';
  577.         Key[64] := 'UNTIL';
  578.         Key[65] := 'VAR';
  579.         Key[66] := 'WHILE';
  580.         Key[67] := 'WITH';
  581.         Key[68] := 'WRITE';
  582.         Key[69] := 'WRITELN';
  583.         Key[70] := 'XOR';
  584.         tab     := CHR(9);  { ASCII Tab character }
  585.         form_feed := CHR(12);  gap  := CHR(32);
  586.         WRITE('List file to console (Y/N)?: ');
  587.         READ(kbd,Ch);
  588.         LISTING := ( (Ch='Y') OR (Ch='y') );
  589.         WRITELN; WRITELN;
  590.     END; {IF ConnectFiles}
  591. END; {of Initialize}
  592.  
  593. BEGIN { Cross Reference }
  594.   CLRSCR;
  595.   WRITELN(' ':22, 'CROSS REFERENCE GENERATOR');
  596.   WRITELN;WRITELN;WRITELN;WRITELN;
  597.   Initialize;
  598.   IF NOT fatal_error THEN
  599.     BEGIN
  600.       WordTree := NIL;          {Make the Tree empty}
  601.       writeln('Pass 1 [Listing] Begins ...');BuildTree(WordTree, FILE_ID);
  602.       close(FOUT) ;
  603.       writeln('Pass 2 [Cross-Ref] Begins ...');PrintTree(WordTree);
  604.       close(XOUT);
  605.     END;
  606.   WRITELN;
  607. END. { Cross Reference }
  608.  
  609.